<?
/*******************************************************************************************/
/*   CLASE DEL MODULO: moduloMetadata                                                       */
/*******************************************************************************************/
class ModuloMetadata extends Modulo
	{
	// Propiedades para el loadClass
		var $oTmpObject;
// Vectores Internos
		var $aAcciones; 		// array de cache de los permisos
		var $aClass;				// array de las clases que tiene la accion actual
		var $aOnLoad;
		var $aOnShow;
		var $oMetadata;

	function ModuloMetadata( $cModule )
	{
		parent::Modulo( $cModule ) ;
	}

	function openMetadata()
	{
		if ( !$this->oMetadata )
		{
			//$this->oMetadata = openDB( DB_PDO , "sqlite:". $this->getPath() .'/db/metadata.sdb');
			
			$this->oMetadata = openDB( DB_SQLITE , $this->getPath() .'/db/metadata.sdb');
		}
	}
	function files()
		{
			$this->openMetadata();
			// Armar un array con las constantes
				$aLineas = file( $this->getPath() . "/tabla_var.php");
				foreach ( $aLineas  as $cLinea )
				{
					$cLinea = trim($cLinea);
					if ( substr($cLinea, 0, 6 ) == 'define' || substr($cLinea, 0, 6 ) == 'DEFINE' )
					{
						$cLinea = str_replace( 'define', '' , $cLinea );
						$cLinea = str_replace( 'DEFINE', '' , $cLinea );
						$cLinea = str_replace( '(', '' , $cLinea );
						$cLinea = str_replace( ')', '' , $cLinea );
						$cLinea = str_replace( ';', '' , $cLinea );
						$cLinea = str_replace( "'", '' , $cLinea );
						list ( $cDefine , $ncAccion  ) = explode ( "," , $cLinea );
						$aDefines[trim($ncAccion)] = trim($cDefine) ;
					}
				}
			// Armar el array de acciones y permisos
				$cSql = "SELECT ncAccion, cIcono, cNombre, ncTipoAccion, cParametro, ncModo FROM stAccion ";
				$aAcciones = $this->oMetadata->getMatrix($cSql);
				foreach ( $aAcciones as $aAccion )
				{
					$cSql = "SELECT  ncActor FROM stPermiso WHERE ncAccion =  " . $aAccion[ncAccion] . ' ORDER BY ncActor';
					$aActores = $this->oMetadata->getArray($cSql);
					if ( $aActores[0] == 0 )
						$cActores = 0;
					else
						$cActores = implode( ',', $aActores );
					$aRoles[$cActores][] = $aAccion;
				}
			// Arma el archivo action_ini
				$cNombreArchivo = $this->getPath() . "/action_ini.php";
				$nFd = fopen( $cNombreArchivo, "w" );
				fwrite( $nFd, '<?	$aRoles = explode( "," , $this->oUserSession->getRol( $this->cModule ) ) ;' . "\n");
				foreach ( $aRoles as $cActores => $aAcciones )
				{
					if ( $cActores != 0 )
					{
						// Manda el if con la condicion de que el sea uno de los roles del usuario
						$aActores = explode( ',' , $cActores );
						$cCondicion = "";
						foreach( $aActores  as $ncActor )
						{
							$cCondicion .=  ' ||  in_array( ' . $ncActor . ', $aRoles)  ' ;
						}
						$cCondicion = substr($cCondicion, 3 );
						fwrite( $nFd,  'if ( ' . $cCondicion . " ) {\n");
					}
					foreach ( $aAcciones as $aAccion )
					{
						$cSql = "SELECT  ncEvento, max(nPaso) FROM stAccionClase WHERE ncAccion =  " . $aAccion[ncAccion] . ' GROUP BY ncEvento';
						$aMaxPaso = $this->oMetadata->getKeyArray($cSql) ;
						$nMaxPaso = ( $aMaxPaso[1] > $aMaxPaso[2] ) ? $aMaxPaso[1] : '';
						$Linea = '$this->aAcciones[' . $aDefines[ $aAccion[ncAccion] ]  . ']	= array ( "cNombre" => "' . $aAccion[cNombre] . '", "cParametros" => "' . $aAccion[cParametro]. '", "ncTipoAccion" => ' . $aAccion[ncTipoAccion]. ', "cIcono" => "' . $aAccion[cIcono] . '", "ncModo" => ' . $aAccion[ncModo] . ($nMaxPaso? ', "nMaxTask" => ' . $nMaxPaso :'') . ' );' . "\n";
						fwrite( $nFd,  $Linea );
					}
					if ( $cActores != 0 ) fwrite( $nFd, "}\n");
				}
				fwrite( $nFd, "?>");
				fclose( $nFd );
			// Arma el archivo event_ini
				$cSql = "SELECT DISTINCT ncAccion, ncEvento, nPaso FROM 	stAccionClase";
				$aAccionClases = $this->oMetadata->getMatrix($cSql);
				$cNombreArchivo = $this->getPath() . "/event_ini.php";
				$nFd = fopen( $cNombreArchivo, "w" );
				fwrite( $nFd, '<?	global $cClass; ' . "\n" . '$cMethod = getParam( PARAM_METHOD ) ;' . "\n");
				fwrite( $nFd, ' switch ( $this->cAction . "_" . $this->cEvent . "_" . $this->nTask ) { ' . "\n");
				foreach ( $aAccionClases as $aAccionClase )
				{
					$cdEvento  = $aAccionClase[ncEvento] == 1 ? 'onLoad':'onShow';
					fwrite( $nFd, '	case ' . $aDefines[ $aAccionClase[ncAccion] ]   . ' . "_' . $cdEvento .'_' . $aAccionClase[nPaso] . '":' );
					$cSql = "SELECT cMetodo, cArchivo, ncEvento, SMo.cDirectorio as cDirectorioSubModulo, cParametro
						FROM 	stAccionClase AS PrC
							JOIN 	stClase as Cla
								ON Cla.ncClase = PrC.ncClase
							LEFT JOIN stSubModulo as SMo
								ON Cla.ncSubModulo = SMo.ncSubModulo
							WHERE ncAccion = " . $aAccionClase[ncAccion] . "
								AND nPaso = " . $aAccionClase[nPaso];
					$aClases = $this->oMetadata->getMatrix($cSql);
					$cLinea = '$aClass = array(';
					foreach ( $aClases as $aClase )
					{
						$cArchivo  = substr($aClase[cArchivo], 0, -4 );
						$cDirectorioSubModulo  = $aClase[cDirectorioSubModulo];
						$cLinea .= "'$cDirectorioSubModulo/$cArchivo' => '" . $aClase[cMetodo] . " " . $aClase[cParametro] . "',";
					}
					$cLinea = substr($cLinea, 0, -1) . " ); break;\n";
					fwrite( $nFd, $cLinea );					
				}
				/*fwrite( $nFd, " } \n ?>");*/
				fwrite( $nFd, '} if ( $this->cEvent == "onLoad" ){ foreach($aClass as $cKey => $cValue ) {list($cSubModulo, $cClase) = explode( "/", $cKey );list($cMetodo, $cParametro) = explode( " ", $cValue );$this->setSubModule($cSubModulo);$oClass = $this->loadClass($cClase);if ( $cMethod ) $oClass->$cMethod(); else$oClass->$cMetodo($cParametro); } if ( $oClass && is_numeric($this->cAction) ) $oClass->close(); } else{foreach($aClass as $cKey => $cValue ) {list($cSubModulo, $cClase) = explode( "/", $cKey );list($cMetodo, $cParametro) = explode( " ", $cValue );if ( $cClass == "" || $cClass == $cClase ) { $this->setSubModule($cSubModulo);$oClass = $this->loadClass($cClase);if ( $cMethod  ) $oClass->$cMethod(); else { echo "<div id=\'$cClase\'>";$oClass->$cMetodo($cParametro); echo "</div>";}}}}?>' );
				fclose( $nFd );
			//
		}
	function data()
		{
			$cTablaFiltro = getParam('tabla');
			$aTables = array();$cReturn ='';
			$oXML = simplexml_load_file( $this->cPath  .  "/db" . strrchr ( $this->cPath  , "/" ) . ".xml" );
			foreach ($oXML->METADATA->TABLES->children() as $table)
			{
				$cTabla = (string)$table->attributes()->Tablename;
				if ( $cTablaFiltro == $cTabla || $cTablaFiltro == '' )
				{
					$cCampos='';
					foreach( $table->COLUMNS->children() as $aColumn )
						$cCampos .= (string)$aColumn->attributes()->ColName . ',';
					$cCampos = substr($cCampos , 0, -1);
					$cSql = "SELECT $cCampos FROM $cTabla ";
					$cReturn  .= "TRUNCATE $cTabla; ";
					$oRecordset = $this->oDatabase->recordset($cSql);
					while ( $oRecordset->moveNext(0) )
					{
						$cValores = "";
						foreach ( $oRecordset->aFields as $cValor )
						{
							//$cValores .= $this->oDatabase->dbValue ( $cValor ) . ", ";
							$cValores .= $this->oDatabase->dbValue ( $cValor ) . ", ";
						}

						$cValores = substr($cValores , 0, -2 ) ;
						$cSqlIns = "INSERT INTO $cTabla ( $cCampos ) VALUES ( $cValores ); \n";
						$cReturn .= $cSqlIns ;
					}
				}
			}			
			header("Content-Type: text/plain");
			header("Content-Disposition: attachment; filename=" . $this->cModule  . ".sql");			
				echo $cReturn ;
			exit();
		}
	function export ()
		{
			$this->data();
		}

	function loadLibrary ( $cLibrary )
		{
			require_once( $this->getPath() . "/$cLibrary" );
		}
	function getRoles()
		{
			$this->openMetadata();
			// Consulta si Tiene Permisos
			// Verifica los permisos por usuario
			$cSql = "SELECT ncActor, cdActor
							FROM 	stActor";
			return  $this->oMetadata->getKeyArray($cSql);
		}
	// Devuelve V o F si el usuario tiene permiso de acceso a una accion.
	function isAllowed( $cAction )
		{
			$this->openMetadata();
			// Consulta si Tiene Permisos
			// Verifica los permisos por usuario
			$cSql = "SELECT ncAccion
							FROM 	stPermiso
							WHERE	ncAccion = $cAction
							AND 	ncActor IN ( 0, " . $this->oUserSession->getRol( $this->cModule )  . " ) ";
			$ncAccion = $this->oMetadata->getData($cSql);
			return ( $ncAccion ) ? true :false;
		}
	// Si $cAction es un String => es un Archivo que esta dentro de su estructura de directorio
	function loadAction ( $cAction, $nTask = 1, $cClassName = '' )
		{
			$this->aOnLoad = array();
			$this->aOnShow = array();
			if ( $nTask == ''  ) $nTask = 1;
			// Guarda la Accion y el Paso Actual
				$this->cAction = $cAction;
				$this->nTask   = $nTask;
			// Si no es una Accion Predefinida (acciones del modulo)
			if ( !is_numeric($cAction)  )
			{
				if ( $cAction == 'files' || $cAction == 'info' || $cAction == 'config' || $cAction == 'doc'|| $cAction == 'status' || $cAction == 'import' || $cAction == 'export'  || $cAction == 'data' ) 
					$this->aOnLoad[] = array ( $this, $cAction );
				else
					define( 'LOAD_MODULE_ACTION', true );
				return true;
			} else
			{
				if ( $this->isAllowed( $cAction ) == false )
				{
					//echo " Accion " . $cAction . " Usuario " . $this->oUserSession->getUser() . "<br>";
					// Si esta loggeado y No tiene Permisos
					if ( $this->oUserSession->isLogged() )
					{
						addMessage("No tiene permisos para acceder a esta accion ( " .$this->cModule . ".$cAction )" );
						return false;
					} else
					{
						if ( $_COOKIE["cLogin"] && !$this->oUserSession->isLogged() )
						{
							$oModSeguridad =& loadModule( "seguridad" );
							$oModSeguridad->setSubModule( "usuario" );
							$oExe = $oModSeguridad->loadClass( "usuario_exe" );
							return $oExe->autoLogin();
						} else
						{
							$this->cUrlBack = '?' . PARAM_MODULE .'=seguridad&amp;' . PARAM_ACTION .'=' . INGRESAR_AL_SISTEMA;
							return -1;
						}
					}
				}
				/// Desbloquea el uso (include) de los archivos.
				define( 'LOAD_MODULE_ACTION', true );
				// Busca las Clases Configuradas en el Paso Actual
				$cSql = "SELECT cArchivo, cMetodo, ncEvento, SMo.cDirectorio as cDirectorioSubModulo, Cla.cDirectorio as cDirectorioClase, cParametro
										FROM 	stAccionClase AS PrC
											JOIN 	stClase as Cla
												ON Cla.ncClase = PrC.ncClase
											LEFT JOIN stSubModulo as SMo
												ON Cla.ncSubModulo = SMo.ncSubModulo
											WHERE	PrC.ncAccion = $cAction";
				// Si es un refresh solo carga esa clase
				if ( $cClassName )
				{
					$cSql .= " AND Cla.cFisico = '$cClassName.php' AND PrC.ncEvento = " . ON_SHOW;
				} else
				{
					$cSql .= " AND PrC.nPaso = $nTask";
				}
				//$cSql .= " ORDER BY PrC.nPaso";
				$aClases = $this->oMetadata->getMatrix($cSql);
				// Por cada clase
				foreach( $aClases as $aClase )
				{
				// Arma el Directorio de la Clase
					$cDirectorio = $aClase['cDirectorioSubModulo'];
					$cMetodo = $aClase['cMetodo'];
					if ( $aClase['cDirectorioClase'] ) $cDirectorio .= "/" . $aClase['cDirectorioClase'] ;
					$this->setSubModule( $cDirectorio );
					switch( $aClase['ncEvento'] )
					{
						case ON_LOAD:
							$this->aOnLoad[] = array ( $this->loadClass( $aClase['cArchivo'] ), $cMetodo );
							break;
						case ON_SHOW:
							$this->aOnShow[] = array ( $this->loadClass( $aClase['cArchivo'] ), $cMetodo , $aClase['cParametro'] );
							break;
					}
				}
				if ( count($this->aOnLoad) > 0 && count($this->aOnShow) == 0 )
				{
					// Si no Existe el proximo paso => redirecciona al Back
					$cSql = "SELECT nPaso FROM stAccionClase WHERE ncAccion = $cAction AND nPaso = " . ($nTask+1);
					$nNextTask = $this->oMetadata->getData($cSql);
					if (  $nNextTask ) {	$this->setRedirect( ACTION_NEXT ); }
					else {					$this->setRedirect( ACTION_BACK ); }
				}
			}
			return true;
		}
	function load()
		{
			$cAction  = $this->getAction();
			if ( is_numeric($this->cAction)  ||  $cAction == 'files' || $cAction == 'info' || $cAction == 'config' || $cAction == 'doc'|| $cAction == 'status' || $cAction == 'import' || $cAction == 'export'  || $cAction == 'data' ) 
			{
				if ( is_array( $this->aOnLoad )  && count($this->aOnLoad ) > 0)
				{
					foreach ( $this->aOnLoad as $aClass )
						{
							$aClass[0]->$aClass[1]();
							//$oClass->exec( $aClase['cMetodo'] );
						}
					if ( is_numeric($cAction) ) $aClass[0]->close();
				}
			}
			else
				$this->loadTemplatePage();
		}
	function show()
		{
			if ( $this->getOutputType() == 'html' &&  $this->cTarget == 'body_main' )
			{
				$this->showMessages();
			}
			if ( !is_numeric($this->cAction)  )
			{
				$this->showTemplatePage();
			} else
			{
				// Si esta en Modo Action (loadAction)
				if ( is_array( $this->aOnShow )  && count($this->aOnShow ) > 0)
				{
					foreach ( $this->aOnShow as $aClass )
						{
							$cClassname = strtolower(get_class( $aClass[0] ) );
							$bDiv = ( $cClassname != $this->cTarget && $this->getOutputType() == 'html'  );
							if ( $bDiv ) echo "<div class='clases' id='$cClassname'>";
							$aClass[0]->$aClass[1]($aClass[2]);
							if ( $bDiv ) echo "</div>";
						}
				}
			}
		}
	function refresh( $cClass , $cMethod = '' )
		{
			// Si la Clase era una de las clases de la accion
			if ( count( $this->aOnShow ) == 1 && strtolower(get_class( $this->aOnShow[0][0] )) == $cClass )
			{
				$oClass = $this->aOnShow[0][0];
				if ( $cMethod == '' ) $cMethod = $this->aOnShow[0][1];
				return $oClass->$cMethod( $this->aOnShow[0][2] );
			} else
			{
				if ( $cMethod == '' ) $cMethod = $this->aOnShow[0][1];
				// Sino la carga y la ejecuta
				$oClass = $this->loadClass($cClass);
				return $oClass->$cMethod();
			}
		}
	// Devuelve un array con ( Url, Icono, Texto )
	function getActionArray( $cAction  )
		{
			$cHRef = $this->makeActionLink( $cAction , '', 1);
			if ( $cHRef != "" )
			{
				return array( $cHRef, $this->aAcciones[$cAction][3], $this->aAcciones[$cAction ][0] );
			}
		}

	function makeAction ( $cValor, $cAction , $cParametros = '', $ncModo = '', $cAccessKey = '', $cTarget = '' )
		{
			$cHRef = $this->makeActionLink( $cAction , $cParametros, $ncModo );
			//$cPropiedades = "onclick='abrirPermisos($cAction );'";
			if ( $cHRef == "" )
			{
				return $cValor;
			} else
			{
				if ( $cValor != '' )
				{
					$cNombre        = $cValor;
					if ( $ncModo == '' ) $ncModo 				= $this->aAcciones[$cAction ][4];
					return $this->makeLink( $cHRef , $cClase, $cNombre , $cIcono, $ncModo, 3, $cTarget, $cAccessKey );
				}
				else
				{
					$ncTipoAccion 	= $this->aAcciones[$cAction ][1];
					$cNombre        = $this->aAcciones[$cAction ][0];
					$cClase		    	= 'accion' . $ncTipoAccion;
					$cIcono         = $this->aAcciones[$cAction ][3];
					if ( $ncModo == '' ) $ncModo 				= $this->aAcciones[$cAction ][4];
					return $this->makeLink( $cHRef , $cClase, $cNombre , $cIcono, $ncModo, $ncTipoAccion, $cTarget, $cAccessKey);
				}
			}
		}
	/// makeActionLink( $cAction , $cParametros = "")
	// verifica si tiene permisos y devuelve un Url
	function makeActionLink( $cAction , $cParametros = "" )
		{
			if ( $this->oUserSession->getUser() == false )
			{
				return false;
			}

			// Si no esta Definido => Busca y lo Agrega
			if ( $this->aAcciones[$cAction ][0] == ""  ) {
				if ( $this->isAllowed( $cAction ) == false )
				{
					$this->aAcciones[$cAction ][0] = "sinpermiso";
					return "";
				}
				// Si tiene Permisos Busca los Datos del Accion para Armar el Link
				$cSql = "SELECT cIcono, cNombre, ncTipoAccion, cParametro, ncModo
							FROM 	stAccion as Pr
							WHERE	Pr.ncAccion = $cAction";
				$aAccion = $this->oMetadata->getArray($cSql);

				$cParamAccion = PARAM_MODULE . "=" . $this->cModule  . "&amp;" . PARAM_ACTION . "=$cAction";

				if ( $aAccion["cParametro"] )
				{
					$cParamAccion .= '&amp;' . $aAccion["cParametro"];
				}
				// Verifica primero si existe el icono es local (en el directorio images de.
				
				$cIcono = $this->cUrlImages . '/'. $aAccion["cIcono"] ;
				//Agrega los datos a un Cache (Array)
				$this->aAcciones[$cAction][0] = $aAccion["cNombre"];
				$this->aAcciones[$cAction][1] = $aAccion["ncTipoAccion"];
				$this->aAcciones[$cAction ][2] = $cParamAccion;
				$this->aAcciones[$cAction ][3] = $cIcono;
				$this->aAcciones[$cAction ][4] = $aAccion["ncModo"];
			}

			if ( $this->aAcciones[$cAction][0] == "sinpermiso"  )
			{
				return "";
			}

			$cParamAccion = $this->aAcciones[$cAction][2];
			// Asigna la Clase
			$cClase = 'accion' . $this->aAcciones[$cAction][1];
			$cNombre = $this->aAcciones[$cAction ][0] ;

			// Arma el Link
			$cHRef = "?";

			if ( !empty($cParamAccion) ) {
				$cHRef .= $cParamAccion ;
				if ( $cHRef[strlen($cHRef)-5] != '&amp;' ) $cHRef .= '&amp;';
			}

			if ( !empty($cParametros) ) {
				$cHRef .= $cParametros ;
				if ( $cHRef[strlen($cHRef)-5] != '&amp;' ) $cHRef .= '&amp;';
			}

			return $cHRef;
		}
	function docAction( $ncAccion )
	{
		$this->openMetadata();
		define( 'LOAD_MODULE_ACTION', true );
		$cSql = "SELECT * FROM stAccion WHERE ncAccion = $ncAccion";
		$aAccion  = $this->oMetadata->getArray($cSql);
		echo "<strong>" .$aAccion['cdAccion'] ."</strong><br/>";
		echo $aAccion['cObjetivo'] . "<br/>";
		$cSql = "SELECT cArchivo, cMetodo, ncEvento, SMo.cDirectorio as cDirectorioSubModulo, Cla.cDirectorio as cDirectorioClase, cParametro
								FROM 	stAccionClase AS PrC
									JOIN 	stClase as Cla
										ON Cla.ncClase = PrC.ncClase
									LEFT JOIN stSubModulo as SMo
										ON Cla.ncSubModulo = SMo.ncSubModulo
									WHERE	PrC.ncAccion = $ncAccion
										AND ncEvento = 2
										AND nPaso = 1"; //" ORDER BY nPaso, ncEvento ";
			$aClases = $this->oMetadata->getMatrix($cSql);
			// Por cada clase
			foreach( $aClases as $aClase )
			{
			// Arma el Directorio de la Clase
				$cDirectorio = $aClase['cDirectorioSubModulo'];
				$cMetodo = $aClase['cMetodo'];
				if ( $aClase['cDirectorioClase'] ) $cDirectorio .= "/" . $aClase['cDirectorioClase'] ;
				$this->setSubModule( $cDirectorio );
				$oClass =  $this->loadClass( $aClase['cArchivo'] );
				echo $oClass->doc($cMetodo, '') ;
			}
	}
	function doc()
		{
			// Si es una accion la documenta y listo
			if ( getParam("ncAccion")  ) return $this->docAction( getParam("ncAccion")  );
			// Documenta todo el Modulo
			/// 1. SubModulos
			$cSql = "SELECT ncSubModulo, cdSubModulo, cDirectorio FROM stSubModulo";
			$this->openMetadata();
			$aSubModulos = $this->oMetadata->getMatrix($cSql);
			$aSubModulos[] = array( '', 'Sin SubModulo', '' );
			$nFdM = fopen( $this->cPath . "/doc/submodulos.htm", "w" ) ;
			fwrite ( $nFdM , "<HTML>" . $this->getStyleSheet () . "<BODY>\n");
			fwrite ( $nFdM , "<h2>Listado de SubModulos de " . $this->cModule . "</h2>\n");

			$cFila = "<TABLE border='1' cellspacing='0' ><TR class='titulo_lst'><TD>Nombre</TD><TD>Entidades</TD><TD>Acciones</TD> </TR>\n";
			fwrite ( $nFdM , $cFila );
			foreach( $aSubModulos as $aSubModulo )
			{
				// Guarda la Fila en la Tabla de SubModulos

				$cColorT = ($nColorT++) % 2 ?  '#E7E7E7':'#FFFFFF';
				$cFila = "<TR bgcolor='$cColorT' class='campo_lst'> <A id='" . $aSubModulo[1] . "'></A> <TD>" . $aSubModulo[1] . "</TD><TD><A href='entidades.htm#" . $aSubModulo[1] . "'>Ver</A></TD><TD><A href='Acciones.htm#" . $aSubModulo[1] . "'>Ver</A></TD> </TR>\n";
				fwrite ( $nFdM , $cFila );
			}
			fwrite ( $nFdM , "</BODY></HTML>\n" );
			fclose ( $nFdM );

			/// 2. Entidades
			// Abre y Guarda el Principio de los Archivos de las Entidades
			$nFdM = fopen( $this->cPath . "/doc/entidades.htm", "w" ) ;
			$nFdD = fopen( $this->cPath . "/doc/entidades_detalle.htm", "w" ) ;
			fwrite ( $nFdM , "<HTML>" . $this->getStyleSheet () . "<BODY>\n");
			fwrite ( $nFdD , "<HTML>" . $this->getStyleSheet () . "<BODY>\n");

			fwrite ( $nFdM , "<h2>Listado de Entidades de " . $this->cModule . "</h2>\n");
			fwrite ( $nFdD , "<h2>Detalle de las Entidades de " . $this->cModule . "</h2>\n");

			// Por cada SubModulo
			foreach( $aSubModulos as $aSubModulo )
			{
				// Por cada Clase Guarda un Registro con la Descripcion
				$cSql = "SELECT ncClase, cFisico, cdClase, cdTipoClase
										FROM stClase as Cla
											JOIN scTipoClase as TCl
												ON TCl.ncTipoClase = Cla.ncTipoClase
										WHERE TCl.ncCategoriaClase = " . CATEGORIA_CLASE_ENTIDAD . "
											AND Cla.ncSubModulo " . ( $aSubModulo[0] == '' ? " IS NULL"  : " = ".$aSubModulo[0] )  . "
										ORDER BY cFisico";

				// Guarda la Cabecera de la Tabla de Clases
				$cFila = "<a id='" . $aSubModulo[1] . "'></a><table width='100%' border='1' cellspacing='0' ><CAPTION>" . $aSubModulo[1] . "</CAPTION><TR class='titulo_lst'><TD>Tabla</TD> <TD>Descripcion</TD> <TD>Tipo</TD><TD>Campos</TD>  </TR>\n";
				fwrite ( $nFdM , $cFila );

				// Ciclo por cada Clase
				$oRecordset = $this->oMetadata->recordset($cSql);
				while ( $oRecordset->moveNext(0) )
				{
					$aTabla = $oRecordset->aFields;

					// Arma una Tabla con los Atributos en entidades_detalle
					$cSql = "SELECT cFisico, cdAtributo, cdClaseAtributo, fLongitud, cdTipoAtributo, cDescripcion
											FROM stClaseAtributo as CAt
											JOIN stClase as Cla
													ON Cla.ncClase = CAt.ncClase
											JOIN scTipoAtributo as TAt
													ON TAt.ncTipoAtributo = CAt.ncTipoAtributo
											WHERE CAt.ncClase = " . $aTabla[0] . "
											ORDER BY CAt.nOrden";
					$aAtributos = $this->oMetadata->getMatrix( $cSql );

					$cFila = "<a id='" . $aTabla[1] . "'></a><table width='100%' border='1' cellspacing='0'><caption class='campo_lst'>" . $aTabla[1]. "</CAPTION><TR class='titulo_lst'> <TD>Campo</TD> <TD>Descripcion</TD> <TD>Tipo de Dato</TD> <TD>Tipo</TD> <TD>Ojetivo</TD> </TR>";
					fwrite ( $nFdD , $cFila );
					foreach ( $aAtributos as $aAtributo )
					{
						$cColorA = ($nColorA++) % 2 ?  '#E7E7E7':'#FFFFFF';
						$cFila = "<TR bgcolor='$cColorA' class='campo_lst'> <TD>" . $aAtributo[0] . "</TD> <TD>" . $aAtributo[1] . "</TD> <TD>" . $aAtributo[2] . ($aAtributo[3] ? '('.$aAtributo[3].')' : '') . "</TD> <TD>" . $aAtributo[4] . "</TD> <TD>" . $aAtributo[5] . "</TD> </TR>\n";
						fwrite ( $nFdD , $cFila );
					}
					fwrite ( $nFdD , "</TABLE><BR>\n" );

					// Guarda la Fila en la Tabla de Entidades
					$cColorT = ($nColorT++) % 2 ?  '#E7E7E7':'#FFFFFF';
					$cFila = "<TR bgcolor='$cColorT' class='campo_lst'> <A id='" . $aAtributo[0] . "'></A> <TD>" . $aTabla[1] . "</TD> <TD>" . $aTabla[2] . "</TD> <TD>" . $aTabla[3] . "</TD><TD><A href='entidades_detalle.htm#" . $aTabla[1] . "'>" . count($aAtributos) . "</A></TD>  </TR>\n";
					fwrite ( $nFdM , $cFila );

				}

				// Guarda el Pie de la Tabla de Clases
				fwrite ( $nFdM , "</TABLE><BR>\n" );
			}
			// Guarda el Final y cierra los Archivos de las Entidades
			fwrite ( $nFdM , "</BODY></HTML>\n" );
			fwrite ( $nFdD , "</BODY></HTML>\n" );
			fclose ( $nFdM );
			fclose ( $nFdD );

			// 3. Acciones
			// Abre y Guarda el Principio de los Archivo de Acciones
			define( 'LOAD_MODULE_ACTION', true );
			$nFdM = fopen( $this->cPath . "/doc/acciones.htm", "w" ) ;
			$nFdD = fopen( $this->cPath . "/doc/acciones_detalle.htm", "w" ) ;
			fwrite ( $nFdM , "<HTML>" . $this->getStyleSheet () . "<BODY>\n");
			fwrite ( $nFdD , "<HTML>" . $this->getStyleSheet () . "<BODY>\n");

			fwrite ( $nFdM , "<h2>Listado de Acciones del Modulo " . $this->cModule . "</h2>\n");
			fwrite ( $nFdD , "<h2>Detalle de Acciones del Modulo  " . $this->cModule . "</h2>\n");

			// Por cada SubModulo
			foreach( $aSubModulos as $aSubModulo )
			{
				// Por cada Clase Guarda un Registro con la Descripcion
				$cSql = "SELECT ncAccion, cNombre, cdAccion, cdTipoAccion, cdModo, cParametro, cObjetivo, cIcono
										FROM stAccion as Pro
											JOIN scTipoAccion as TPr
												ON TPr.ncTipoAccion = Pro.ncTipoAccion
											JOIN scModo as TMo
												ON TMo.ncModo = Pro.ncModo
										WHERE Pro.ncSubModulo " . ( $aSubModulo[0] == '' ? " IS NULL"  : " = ".$aSubModulo[0] )  . "
										ORDER BY cdAccion";

				// Guarda la Cabecera de la Tabla de Acciones
				$cFila = "<A id='" . $aSubModulo[1] . "'></a><table width='100%' border='1' cellspacing='0' ><CAPTION>" . $aSubModulo[1] . "</CAPTION><TR class='titulo_lst'><TD>Icono</TD><TD>Nombre</TD><TD>Tipo</TD><TD>Objetivo</TD><TD>Permisos</TD></TR>\n";
				fwrite ( $nFdM , $cFila );

				// Ciclo por cada Accion
				$oRecordset = $this->oMetadata->recordset($cSql);
				while ( $oRecordset->moveNext(0) )
				{
					$aAccion = $oRecordset->aFields;
					// Obtiene los Actores
					$aActores = $this->oMetadata->getArray("SELECT cdActor FROM stActor WHERE ncActor IN (SELECT ncActor FROM stPermiso WHERE ncAccion = " . $aAccion[0] . ") ");
					$cActores = implode(",", $aActores );
					// 1.Nombre, 2.Descripcion, 3.Tipo, 4.Modo, Actores, 5.Parametros, Interfaces, Control, 6.Objetivo, 6
					// Guarda la Fila en la Tabla de Acciones
					$cColorT = ($nColorT++) % 2 ?  '#E7E7E7':'#FFFFFF';
					$cFila = "<TR bgcolor='$cColorT' class='campo_lst'> <A id='" . $aAccion[2] . "'></A> <TD><a href='acciones_detalle.htm#" . $aAccion[2] . "'><img src='" . $this->cUrlImages . "/" .$aAccion[7] . "'/></a></TD> <TD>" . $aAccion[2] . "</TD> <TD>" . $aAccion[3] . "</TD> <TD>" . $aAccion[6] . "</TD> <TD>" . $cActores . "</TD> </TR>\n";
					fwrite ( $nFdM , $cFila );

					$cFila = "<A id='" . $aAccion[2] . "'></A><img src='" . $this->cUrlImages . "/" .$aAccion[7] . "'/> " . $aAccion[2] . "<BR/>\n";
					fwrite ( $nFdD , $cFila );
					// Busca las Clases
					$cSql = "SELECT cArchivo, cMetodo, ncEvento, SMo.cDirectorio as cDirectorioSubModulo, Cla.cDirectorio as cDirectorioClase, cParametro
											FROM 	stAccionClase AS PrC
												JOIN 	stClase as Cla
													ON Cla.ncClase = PrC.ncClase
												LEFT JOIN stSubModulo as SMo
													ON Cla.ncSubModulo = SMo.ncSubModulo
												WHERE	PrC.ncAccion = " . $aAccion[0] . " ORDER BY nPaso, ncEvento ";
						$aClases = $this->oMetadata->getMatrix($cSql);
						// Por cada clase
						foreach( $aClases as $aClase )
						{
						// Arma el Directorio de la Clase
							$cDirectorio = $aClase['cDirectorioSubModulo'];
							$cMetodo = $aClase['cMetodo'];
							if ( $aClase['cDirectorioClase'] ) $cDirectorio .= "/" . $aClase['cDirectorioClase'] ;
							$this->setSubModule( $cDirectorio );
							$oClass =  $this->loadClass( $aClase['cArchivo'] );

							fwrite ( $nFdD , $oClass->doc($cMetodo, '')  );
						}
				}

				// Guarda el Pie de la Tabla de Clases
				fwrite ( $nFdD , "</TABLE><BR>\n" );
				fwrite ( $nFdM , "</TABLE><BR>\n" );
			}
			// Guarda el Final y cierra los Archivos de las Acciones
			fwrite ( $nFdM , "</BODY></HTML>\n" );
			fwrite ( $nFdD , "</BODY></HTML>\n" );
			fclose ( $nFdM );
			fclose ( $nFdD );
		}

	function &loadClass ( $cClass )
		{
		// Agrega el .php si no lo trae y lo pasa a lower case
				$cClass = strtolower( $cClass );
				if ( substr( $cClass, -4) != '.php' ) $cClass .= '.php' ;
			if ( empty( $this->aClass[$cClass] ) )
			{
				// Si esta anidado
					if ( isset( $this->oTmpObject ) )
					{
						$oAuxiliar = &$this->oTmpObject;
					}
				// Arma el Nombre Completo del Archivo
					$cArchivo = $this->getPath();
					if ( $this->cSubModule ) $cArchivo .= '/' . $this->cSubModule;
					$cArchivo .= '/' . $cClass;
				// Verifica que Exista
					if( !file_exists ( $cArchivo ) )
					{
						die( "La clase $cArchivo no existe " );
					}
				// Incluye en Archivo de la Clase (que debe agregar un objeto en el Array de Clases)
					include_once ( $cArchivo ) ;
					if ( isset( $this->oTmpObject ) )
					{
					// Lo Pasa al Vector de Clases
						$this->aClass[$cClass] = &$this->oTmpObject;
						unset($this->oTmpObject);
					} else
					{
						die( "No se pudo crear la clase $cArchivo " . $this->cModule );
					}
				// Si esta anidado
					if ( isset( $oAuxiliar) )
					{
						$this->oTmpObject = &$oAuxiliar;
					}
			}
			// Devuelve la referencia al objeto nuevo
			return $this->aClass[$cClass];
		}
	}
?>